package com.kun.alldb.util;

import com.kun.alldb.support.DBManager;
import com.kun.alldb.base.DatasourceBase;
import com.kun.alldb.support.Plugin;
import com.kun.alldb.support.MetaManager;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.concurrent.ConcurrentHashMap;

/**
 * spi 加载类工厂
 *
 * @author kun.li
 */
public class ServerLoadFactoryUtil {
    /**
     * 增加插件缓存
     * key : dbType
     * value: 具体的插件
     */
    private static final Map<String, Plugin> pluginCacheMap = new ConcurrentHashMap<>();


    public static MetaManager createMetaData(DatasourceBase datasourceBase) {
        return createDialectPlus(datasourceBase.getDsType()).createMetaManager(datasourceBase);
    }


    public static DBManager createDBManager(DatasourceBase datasourceBase) {
        Plugin dialectPlus = createDialectPlus(datasourceBase.getDsType());
        return dialectPlus.createDBManager(datasourceBase);
    }


    public static Plugin createDialectPlus(String dbType) {
        Plugin plugin = pluginCacheMap.get(dbType);
        if (plugin != null) {
            return plugin;
        }
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        List<Plugin> dialectPluses = discoverFactories(loader);
        List<Plugin> dialectPlusList = dialectPluses.stream().filter(dialectPlus -> dialectPlus.supportType(dbType)).toList();
        if (dialectPlusList.size() > 1) {
            throw new RuntimeException("找到多个实现类");
        }
        plugin = dialectPlusList.get(0);
        pluginCacheMap.put(dbType, plugin);
        return plugin;
    }


    private static List<Plugin> discoverFactories(ClassLoader classLoader) {
        final List<Plugin> result = new LinkedList<>();
        ServiceLoader.load(Plugin.class, classLoader).iterator().forEachRemaining(result::add);
        return result;
    }

}
